package com.mikufufu.blog.utils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class AesUtils {

    private static final String AES = "AES";

    private static final String ALGORITHM = "AES/CBC/PKCS5Padding";

    private static final String KEY = "MIKUFUFU1010MENG";
    private static final String IV = "MOXIAOLIMIKUFUFU";

    /**
     * 使用默认密钥和IV加密明文数据
     *
     * @param plaintext 待加密的原始文本（UTF-8编码）
     * @return Base64编码的加密结果字符串
     * @throws Exception 当加密过程失败时抛出异常
     */
    public static String encrypt(String plaintext) throws Exception {
        return encrypt(plaintext, KEY, IV);
    }

    /**
     * 使用默认密钥和IV解密密文数据
     *
     * @param ciphertext Base64编码的加密结果字符串
     * @return 解密后的原始文本（UTF-8编码）
     * @throws Exception 当解密过程失败时抛出异常
     */
    public static String decrypt(String ciphertext) throws Exception {
        return decrypt(ciphertext, KEY, IV);
    }

    /**
     * 使用AES算法加密明文数据
     *
     * @param plaintext 待加密的原始文本（UTF-8编码）
     * @param key AES密钥，长度必须为16/24/32字节（对应128/192/256位）
     * @param iv 初始化向量(IV)，长度必须与算法块大小一致（通常16字节）
     * @return Base64编码的加密结果字符串
     * @throws Exception 当密钥不符合规范或加密过程失败时抛出异常
     */
    public static String encrypt(String plaintext, String key, String iv) throws Exception {
        validateKey(key);
        // 初始化密钥材料和加密参数
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), AES);
        IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes());

        // 配置加密器并执行加密操作
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
        byte[] encrypted = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));

        return Base64.getEncoder().encodeToString(encrypted);
    }

    /**
     * 解密AES加密的Base64字符串
     *
     * @param ciphertext Base64编码的加密字符串
     * @param key AES密钥，必须与加密时使用的密钥一致
     * @param iv 初始化向量，必须与加密时使用的IV一致
     * @return 解密后的原始文本（UTF-8编码）
     * @throws Exception 当密钥不符合规范或解密过程失败时抛出异常
     */
    public static String decrypt(String ciphertext, String key, String iv) throws Exception {
        validateKey(key);
        // 准备解密所需的密钥材料和参数
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), AES);
        IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes());

        // 配置解密器并执行解密流程
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
        byte[] decoded = Base64.getDecoder().decode(ciphertext);

        return new String(cipher.doFinal(decoded), StandardCharsets.UTF_8);
    }

    /**
     * 验证AES密钥长度的有效性
     * @param key 待验证的密钥字符串
     * @throws IllegalArgumentException 当密钥长度不符合AES标准时抛出
     */
    private static void validateKey(String key) {
        if (key.length() != 16 && key.length() != 24 && key.length() != 32) {
            throw new IllegalArgumentException("密钥长度必须为16/24/32字节");
        }
    }

}